Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

deMath.hpp

Go to the documentation of this file.
00001 ///////////////////////////////////////////////////////////////////////////////
00002 /// @file deMath.hpp
00003 ///
00004 /// @brief Math lib header
00005 ///
00006 /// @author Assassin
00007 ///
00008 /// This file is the intellectual property of Novus Delta, LLC.. Usage of the
00009 /// contents of this file is subject to the Destiny3D Member License which
00010 /// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
00011 ///
00012 /// This file is distributed "AS IS" without warranty of any kind.  Novus
00013 /// Delta, LLC. does not guarantee the fitness of the contents of this file
00014 /// for any particular purpose.
00015 ///
00016 /// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
00017 ///
00018 /// <hr>
00019 ///                                 Change History
00020 /// <hr>
00021 ///
00022 /// @date Jan 2002
00023 /// @author Assassin
00024 /// @remarks Creation
00025 ///
00026 /// @date Jul 2002
00027 /// @author Hootie
00028 /// @remarks Convert to static lib
00029 ///
00030 ///////////////////////////////////////////////////////////////////////////////
00031 
00032 #ifndef DEMATH_HPP
00033 #define DEMATH_HPP
00034 
00035 #if defined(USING_DESTINY3D) || defined(USING_DESTINY3D_DLL)
00036 #ifdef _DEBUG
00037 // no static link option
00038 #pragma comment(lib, "deMathd")
00039 #else
00040 #pragma comment(lib, "deMath")
00041 #endif //_DEBUG
00042 #endif //USING_DESTINY3D
00043 
00044 
00045 #include "deGlobalTypes.hpp"
00046 #include "deStack.hpp"
00047 #include <cmath>
00048 
00049 
00050 
00051 struct deFractionInfo
00052 {
00053 protected:
00054     int m_Num, m_Den;
00055     friend class deFraction;
00056 };
00057 class deFraction : public deFractionInfo
00058 {
00059 public:
00060     inline deFraction()
00061         { m_Num = 0; m_Den = 1; }
00062     inline deFraction(int Num)
00063         { m_Num = Num; m_Den = 1; }
00064     inline deFraction(int Num, int Den)
00065         { m_Num = Num; m_Den = Den; }
00066     inline deFraction(const deFraction & ref)
00067         { m_Num = ref.m_Num; m_Den = ref.m_Den; }
00068     inline deFraction(const deFractionInfo & ref)
00069         { m_Num = ref.m_Num; m_Den = ref.m_Den; }
00070     inline ~deFraction() {}
00071 
00072     inline operator double() const { return ((double)m_Num)/m_Den; }
00073     inline operator float() const { return ((float)m_Num)/m_Den; }
00074     inline int Num() const { return m_Num; }
00075     inline int Den() const { return m_Den; }
00076 
00077     inline deFraction operator+(const deFraction & rhs) const
00078         { deFraction ret(*this); ret += rhs; return ret; }
00079     inline deFraction operator-(const deFraction & rhs) const
00080         { deFraction ret(*this); ret -= rhs; return ret; }
00081     inline deFraction operator*(const deFraction & rhs) const
00082         { deFraction ret(*this); ret *= rhs; return ret; }
00083     inline deFraction operator/(const deFraction & rhs) const
00084         { deFraction ret(*this); ret /= rhs; return ret; }
00085     
00086     deFraction operator+(int rhs) const;
00087     deFraction operator-(int rhs) const;
00088     deFraction operator*(int rhs) const;
00089     deFraction operator/(int rhs) const;
00090 
00091     deFraction& operator+=(const deFraction & rhs);
00092     deFraction& operator-=(const deFraction & rhs);
00093     inline deFraction& operator*=(const deFraction & rhs)
00094         { m_Num *= rhs.m_Num; m_Den *= rhs.m_Den; return *this; }
00095     inline deFraction& operator/=(const deFraction & rhs)
00096         { m_Num *= rhs.m_Den; m_Den *= rhs.m_Num; return *this; }
00097     
00098     inline const deFraction& operator=(const deFraction & rhs)
00099         { m_Num = rhs.m_Num; m_Den = rhs.m_Den; return *this; }
00100     inline const deFraction& operator=(int rhs)
00101         { m_Num = rhs; m_Den = 1; return *this; }
00102     bool operator==(const deFraction & rhs);
00103     bool operator==(int rhs);
00104 };
00105 
00106 /// storage class for a Destiny3D transform
00107 struct deTransformInfo
00108 {
00109 public:
00110     deVec3d Translation;    ///< translation, in coordinate space of parent system
00111     deVec3d R,U,I;          ///< basis vectors, hopefully orthogonal for a rigid-body transform
00112     deBoolean m_Identity;   ///< quick bypass value used if the basis vectors form a 3x3 identity matrix. Do not alter manually, use deTransform::TestIdentity
00113 };
00114 /// rigid-body transformation. supports a translation and rotation, with possible scaling.
00115 class deTransform : public deTransformInfo
00116 {
00117 public:
00118     inline ~deTransform() {}
00119     /// default constructor initializes to identity matrix.
00120     inline deTransform(void)
00121         { m_Identity = deTRUE; R = U = I = Translation = deZeroVec; R.X = U.Y = I.Z = 1.0; }
00122     /// copy constructor.
00123     inline deTransform(const deTransformInfo & ref)
00124         { m_Identity = ref.m_Identity; R = ref.R; U = ref.U; I = ref.I; Translation = ref.Translation; }
00125     /// translation constructor, sets rotation to identity.
00126     deTransform(const deVec3d & Trans)
00127         { m_Identity = deTRUE; R = U = I = deZeroVec; R.X = U.Y = I.Z = 1.0; Translation = Trans; }
00128     /// rotation constructor, sets translation to identity.
00129     deTransform(const deVec3d & Right, const deVec3d & Up, const deVec3d & In);
00130     /// all data constructor.
00131     deTransform(const deVec3d & Right, const deVec3d & Up, const deVec3d & In, const deVec3d & Trans);
00132     
00133     /// reset the transform to 0 translation and identity rotation
00134     void inline Reset()
00135         { m_Identity = deTRUE; R = U = I = Translation = deZeroVec; R.X = U.Y = I.Z = 1.0; }
00136     /// convert from a 4x4 matrix, such as an opengl or direct3d one. the last column will be ignored.
00137     void FromFloat44(const float Mat[4][4], deBoolean d3d);
00138     /// convert from a 4x4 matrix, such as deMatrix44.
00139     void FromDouble44(const double Mat[4][4], deBoolean d3d);
00140     /// convert to a 4x4 matrix, such as an opengl or direct3d one. the last column will be created with (0,0,0,1).
00141     void ToFloat44(float Mat[4][4], deBoolean d3d) const;
00142     /// forces any values that are close to 0 to become exactly 0
00143     void SqueezeVectors();
00144     /// set the "right" (aka X or i) basis vector
00145     void SetRight(const deVec3d & Right);
00146     /// set the "up" (aka Y or j) basis vector
00147     void SetUp(const deVec3d & Up);
00148     /// set the "in" (aka Z or k) basis vector
00149     void SetIn(const deVec3d & In);
00150     /// set the translation of the transform. translation is in the space of the parent's coordinate system.
00151     void inline SetTranslation(const deVec3d & Trans) { Translation = Trans; }
00152     /// set all the basis vectors at once
00153     void SetRightUpIn(const deVec3d & Right, const deVec3d & Up, const deVec3d & In);
00154     /// Reset the transform and then build a rotation around the X axis. Any existing rotation or translation is lost.
00155     void SetXRot(deDouble r);
00156     /// Reset the transform and then build a rotation around the Y axis. Any existing rotation or translation is lost.
00157     void SetYRot(deDouble r);
00158     /// Reset the transform and then build a rotation around the Z axis. Any existing rotation or translation is lost.
00159     void SetZRot(deDouble r);
00160     /// Applies a rotation around the X axis to the existing data in the transform.
00161     void RotateX(deDouble Rads);
00162     /// Applies a rotation around the Y axis to the existing data in the transform.
00163     void RotateY(deDouble Rads);
00164     /// Applies a rotation around the Z axis to the existing data in the transform.
00165     void RotateZ(deDouble Rads);
00166     /// Builds a Euler angles rotation, losing any previously stored rotation or translation.
00167     void FreeRot(const deVec3d &Rads);
00168     /// Builds a Euler angles rotation, losing any previously stored rotation or translation.
00169     void FreeRot(deDouble x, deDouble y, deDouble z);
00170     /// Builds a Euler angles rotation, losing any previously stored rotation, but not translation.
00171     void FreeRotInPlace(const deVec3d &Rads);
00172     /// Builds a Euler angles rotation, losing any previously stored rotation, but not translation.
00173     void FreeRotInPlace(deDouble x, deDouble y, deDouble z);
00174     /// Scale the basis vectors by a uniform value.
00175     void ApplyScaling(deDouble UniformScaling);
00176     /// Scale the basis vectors by a distinct axis values.
00177     void ApplyScaling(const deVec3d & Multiples);
00178     /// Scale the basis vectors by a distinct axis values.
00179     void ApplyScaling(deDouble x, deDouble y, deDouble z);
00180     /// Obtain the lengths of the basis vectors (axes) of the transform
00181     void GetBasisScales(deDouble& x, deDouble& y, deDouble &z);
00182     inline void GetBasisScales(deVec3d& v) { GetBasisScales(v.x, v.y, v.z); }
00183 
00184     /// Tests whether the basis vectors form an identity matrix, setting the internal m_Identity member appropriately.
00185     deBoolean TestIdentity(deDouble Epsilon = 0.00001);
00186     /// Tests whether the basis vectors form an orthogonal basis (all perpendicular to one another).
00187     deBoolean IsOrthogonal() const;
00188     /// Tests the basis vectors for an orthonormality (all perpendicular to one another and magnitude=1.0).
00189     deBoolean IsOrthoNormal() const;
00190     /// Creates an orthonormal basis from the existing basis vectors.
00191     deBoolean OrthoNormalize();
00192 
00193     /// retrieve the "right" basis vector
00194     void GetRight(deVec3d & r) const;
00195     /// retrieve the "up" basis vector
00196     void GetUp(deVec3d & u) const;
00197     /// retrieve the "in" basis vector
00198     void GetIn(deVec3d & i) const;
00199     /// retrieve the "right" basis vector
00200     deVec3d GetRight() const;
00201     /// retrieve the "up" basis vector
00202     deVec3d GetUp() const;
00203     /// retrieve the "in" basis vector
00204     deVec3d GetIn() const;
00205     /// retrieve all the basis vectors at once
00206     void GetRightUpIn(deVec3d & Right, deVec3d & Up, deVec3d & In) const;
00207     /// Get a transposition of the rotation matrix, combined with a processed translation.
00208     /// On an orthonormal transform, this is the same operation as computing the inverse, but much quicker to compute.
00209     void GetTranspose(deTransformInfo & target);
00210     /// alternate form of GetTranspose
00211     deTransformInfo GetTranspose();
00212     /// retrieve the translation for this transform
00213     deVec3d inline GetTranslation() const
00214         { return Translation; }
00215 
00216     /// Perform a transformation of a 3d vector using this transform.
00217     void Transform(deVec3d InVec, deVec3d & OutVec) const;
00218     /// Perform a transformation of an array of 3d vectors using this transform.
00219     void TransformArray(const deVec3d InVec[], deVec3d OutVec[], int num) const;
00220     void Transform(deVertex InVec, deVertex & OutVec) const;
00221     void TransformArray(const deVertex InVec[], deVertex OutVec[], int num) const;
00222     /// transform a 3d vector by the transposition of this transform, which is the same as the inverse for orthonormal transforms.
00223     void TransposeTransform(deVec3d InVec, deVec3d & OutVec) const;
00224     /// concatenate this transform with another transform, storing the result in "ret".
00225     /// ret = this * rhs
00226     void Multiply(const deTransformInfo & rhs, deTransformInfo & ret);
00227     /// return = this * rhs
00228     deTransform Multiply(const deTransformInfo & rhs);
00229 };
00230 
00231 struct deVec4d
00232 {
00233     deDouble x,y,z,w;
00234 };
00235 class deMatrix44
00236 {
00237     // uses direct3d matrix layout
00238 public:
00239     union {
00240         struct {
00241             deDouble        _00, _01, _02, _03;
00242             deDouble        _10, _11, _12, _13;
00243             deDouble        _20, _21, _22, _23;
00244             deDouble        _30, _31, _32, _33;
00245         };
00246         deDouble m[4][4];
00247     };
00248     inline ~deMatrix44() {}
00249     inline deMatrix44() {}
00250     inline deMatrix44(const deTransformInfo & ref)
00251     {   
00252         _00 = ref.R.x; _01 = ref.R.y; _02 = ref.R.z; _03 = 0;
00253         _10 = ref.U.x; _11 = ref.U.y; _12 = ref.U.z; _13 = 0;
00254         _20 = ref.I.x; _21 = ref.I.y; _22 = ref.I.z; _23 = 0;
00255         _30 = ref.Translation.x; _31 = ref.Translation.y; _32 = ref.Translation.z;
00256         _33 = 1;
00257     }
00258     deMatrix44(const deVec3d & Right, const deVec3d & Up, const deVec3d & In, const deVec3d & Trans = deZeroVec)
00259     {   
00260         _00 = Right.x; _01 = Right.y; _02 = Right.z; _03 = 0;
00261         _10 = Up.x;    _11 = Up.y;    _12 = Up.z;    _13 = 0;
00262         _20 = In.x;    _21 = In.y;    _22 = In.z;    _23 = 0;
00263         _30 = Trans.x; _31 = Trans.y; _32 = Trans.z; _33 = 1;
00264     }
00265     deMatrix44(const deFloat f[4][4], deBoolean d3d);
00266     deMatrix44(const deDouble d[4][4], deBoolean d3d);
00267     void operator=(const deDouble d[4][4]);
00268 
00269     void Identity()
00270     {
00271         _00 = 1; _01 = 0; _02 = 0; _03 = 0;
00272         _10 = 0; _11 = 1; _12 = 0; _13 = 0;
00273         _20 = 0; _21 = 0; _22 = 1; _23 = 0;
00274         _30 = 0; _31 = 0; _32 = 0; _33 = 1;
00275     }
00276     void Translation(const deVec3d & T)
00277     {
00278         _00 = 1;   _01 = 0;   _02 = 0;   _03 = 0;
00279         _10 = 0;   _11 = 1;   _12 = 0;   _13 = 0;
00280         _20 = 0;   _21 = 0;   _22 = 1;   _23 = 0;
00281         _30 = T.x; _31 = T.y; _32 = T.z; _33 = 1;
00282     }
00283     void Scaling(deDouble x, deDouble y, deDouble z)
00284     {
00285         _00 = x; _01 = 0; _02 = 0; _03 = 0;
00286         _10 = 0; _11 = y; _12 = 0; _13 = 0;
00287         _20 = 0; _21 = 0; _22 = z; _23 = 0;
00288         _30 = 0; _31 = 0; _32 = 0; _33 = 1;
00289     }
00290     void Multiply(const deMatrix44 & right, deMatrix44 & out) const;
00291     void Transform(const deVec3d & in, deVec3d & out) const;
00292     void Transform(const deVec3d & in, deVec4d & out) const;
00293     void Transform(const deVertex & in, deVec4d & out) const;
00294 };
00295 
00296 
00297 /// a class for maintaining a hierarchy of transformations.
00298 /// concatenations are performed with first-in on the left.
00299 class deTransformStack
00300 {
00301 private:
00302     deTStack <deTransform> m_Stack;
00303 
00304 public:
00305     inline deTransformStack() : m_Stack(deTStack<deTransform>::LIFO_STACK) {}
00306     inline ~deTransformStack() {}
00307 
00308     /// compute the concatenation of a transform with the previous top of the stack, and store the concatenation as the new top.
00309     deBoolean Push(const deTransformInfo & transform, deTransformInfo * concat = NULL);
00310     /// remove the last-inserted transform from the stack
00311     deBoolean Pop(deTransformInfo & transform);
00312     /// remove the last-inserted transform from the stack
00313     deBoolean Pop();
00314     /// view the concatenation of all the currently-stored transforms
00315     deBoolean Peek(deTransformInfo & transform);
00316 
00317     /// remove all the transforms from this structure
00318     inline deBoolean Clear() { m_Stack.Clear();}
00319 };
00320 
00321 
00322 /// a quaternion calculation class
00323 class deQuaternion {
00324 public:
00325     union
00326     {   struct
00327         {
00328             deDouble x, y, z;
00329         };
00330         deVec3d vector;
00331     };
00332     deDouble w;
00333 
00334     // A quaternion's length must be closer than this tolerance to 1.0 to be
00335     // considered a unit quaternion
00336     static const deDouble UNIT_TOLERANCE;
00337 
00338     // Epsilon used in spherical linear interpolation
00339     static const deDouble SLERP_EPSILON;
00340 
00341     // Operators
00342     void operator +=(const deQuaternion&);
00343     void operator -=(const deQuaternion&);
00344     void operator *=(const deQuaternion&);
00345     deQuaternion operator +(const deQuaternion&) const;
00346     deQuaternion operator -(const deQuaternion&) const;
00347     deQuaternion operator *(const deQuaternion&) const;
00348     bool operator ==(const deQuaternion&) const;
00349     bool operator !=(const deQuaternion&) const;
00350 
00351     // Conversion operators
00352     operator deVec3d&(){ return vector; }
00353     operator const deVec3d&() const { return vector; }
00354 
00355     // Analytical functions
00356     deBoolean IsValid() const;
00357     deBoolean IsUnit() const;
00358 
00359     // Math operations
00360     // These are slightly faster than the +, -, * operators since they don't use the stack to
00361     // return the result.
00362     // NOTE: These functions are still slower than the +=, -= or *= operators.
00363     void Multiply(const deQuaternion &q, deQuaternion &result) const;
00364     void Add(const deQuaternion &q, deQuaternion &result) const;
00365     void Subtract(const deQuaternion &q, deQuaternion &result) const;
00366 
00367     void Set(deDouble xAxis, deDouble yAxis, deDouble zAxis, deDouble wAxis)
00368         { x = xAxis;    y = yAxis;  z = zAxis;  w = wAxis; }
00369 
00370     // Length of quaternion (also known as 'magnitude')
00371     deDouble Length() const;
00372 
00373     // Normalize quaternion
00374     void Normalize();
00375 
00376     // Interpolate between two quaternions
00377     // If balance is 0, the result is 'this', if balance is 1.0 the result is 'q'
00378     // NOTE: The balance must >= 0 and <= 1
00379     void Interpolate(const deQuaternion &q, deDouble balance, deQuaternion &result);
00380 
00381     void RotateX(deDouble radians){ x += radians; }
00382     void RotateY(deDouble radians){ y += radians; }
00383     void RotateZ(deDouble radians){ z += radians; }
00384 
00385     // Conversion
00386     deBoolean FromMatrix(const deTransformInfo &matrix);
00387 
00388     // NOTE: The translation of the matrix remains unchanged.
00389     void ToMatrix(deTransformInfo &matrix) const;
00390 
00391     deQuaternion(){}
00392     deQuaternion(deDouble xAxis, deDouble yAxis, deDouble zAxis, deDouble wAxis){ x = xAxis;    y = yAxis;  z = zAxis;  w = wAxis; }
00393     deQuaternion(deVec3d &axisdeVector, deDouble www){ vector = axisdeVector; w = www;}
00394 
00395 };
00396 
00397 
00398 
00399 template <typename T>
00400 static inline T SQUARE(T x) {return (x)*(x);}
00401 /// squared length of a deVec3d
00402 static inline deDouble Vec3d_LengthSq(const deVec3d& v)
00403     {return SQUARE(v.X) + SQUARE(v.Y) + SQUARE(v.Z);}
00404 /// length of a deVec3d
00405 static inline deDouble Vec3d_Length(const deVec3d& v)
00406     {return sqrt(Vec3d_LengthSq(v));}
00407 /// multiply each component of a deVec3d by the corresponding component of another
00408 static inline void Vec3d_ScaleByVec(deVec3d & v1, const deVec3d & v2)
00409     { v1.X *= v2.X; v1.Y *= v2.Y; v1.Z *= v2.Z; }
00410 /// compare equality of 2 floating-point values, within some Epsilon value
00411 static inline deBoolean Compare_Epsilon(const deDouble d1, const deDouble d2, deDouble epsilon = 0.00001)
00412     { return (fabs(d1 - d2) <= epsilon); }
00413 /// compare equality of two deVec3d, within some Epsilon value
00414 static inline deBoolean Vec3d_Compare(const deVec3d & v1, const deVec3d &v2, deDouble epsilon = 0.00001)
00415     { return ((fabs(v1.x - v2.x) <= epsilon) && (fabs(v1.y - v2.y) <= epsilon) && (fabs(v1.z - v2.z) <= epsilon)); }
00416 /// compare exact opposite equality of two deVec3d, within some Epsilon value
00417 static inline deBoolean Vec3d_CompareOpposite(const deVec3d & v1, const deVec3d &v2, deDouble epsilon = 0.00001)
00418     { return ((fabs(v1.x + v2.x) <= epsilon) && (fabs(v1.y + v2.y) <= epsilon) && (fabs(v1.z + v2.z) <= epsilon)); }
00419 /// compute the dot-product of two deVec3d (deDouble components)
00420 static inline deDouble Vec3d_Dot(const deVec3d& v1, const deVec3d& v2)
00421     { return (v1).X*(v2).X+(v1).Y*(v2).Y+(v1).Z*(v2).Z; }
00422 /// compute the dot-product of two deVertex (deFloat components)
00423 static inline deFloat Vec3d_Dot(const deVertex& v1, const deVertex& v2)
00424     { return (v1).X*(v2).X+(v1).Y*(v2).Y+(v1).Z*(v2).Z; }
00425 /// compute the square of the distance between two deVec3d
00426 static inline deDouble Vec3d_DistSq(const deVec3d & v1, const deVec3d & v2) 
00427     { 
00428         deDouble Temp1, Temp2; 
00429         Temp1=(v1).x-(v2).x; Temp2 = SQUARE(Temp1); 
00430         Temp1=(v1).y-(v2).y; Temp2 += SQUARE(Temp1);
00431         Temp1=(v1).z-(v2).z; Temp2 += SQUARE(Temp1);
00432         return Temp2;
00433     }
00434 /// compute the distance between two deVec3d
00435 static inline deDouble Vec3d_Dist(const deVec3d & v1, const deVec3d & v2) 
00436     { return (deDouble)sqrt(Vec3d_DistSq(v1,v2));}
00437 /// compute the square of the distance between two deVertex
00438 static inline deFloat Vec3d_DistSq(const deVertex & v1, const deVertex & v2) 
00439     { 
00440         deFloat Temp1, Temp2; 
00441         Temp1=(v1).x-(v2).x; Temp2 = SQUARE(Temp1); 
00442         Temp1=(v1).y-(v2).y; Temp2 += SQUARE(Temp1);
00443         Temp1=(v1).z-(v2).z; Temp2 += SQUARE(Temp1);
00444         return Temp2;
00445     }
00446 /// compute the distance between two deVertex
00447 static inline deFloat Vec3d_Dist(const deVertex & v1, const deVertex & v2) 
00448     { return (deFloat)sqrtf(Vec3d_DistSq(v1, v2));}
00449 /// compute the inverse of a deVec3d (overloaded operator-)
00450 static inline deVec3d operator-(const deVec3d &v)
00451     {deVec3d ret={-v.x,-v.y,-v.z};return ret;}
00452 /// compute the component difference between two deVec3d (overloaded operator-)
00453 static inline deVec3d operator-(const deVec3d &v1, const deVec3d &v2)
00454     {deVec3d ret={v1.x-v2.x,v1.y-v2.y,v1.z-v2.z};return ret;}
00455 /// compute the component sum of two deVec3d (overloaded operator+)
00456 static inline deVec3d operator+(const deVec3d &v1, const deVec3d &v2)
00457     {deVec3d ret={v1.x+v2.x,v1.y+v2.y,v1.z+v2.z};return ret;}
00458 /// compute the scalar product of a deVec3d and a floating-point value (overloaded operator*)
00459 static inline deVec3d operator*(const deVec3d &v1, deDouble d)
00460     {deVec3d ret={v1.x*d,v1.y*d,v1.z*d};return ret;}
00461 /// subtract a deVec3d from another one (overloaded operator-=)
00462 static inline void operator-=(deVec3d &v1, const deVec3d &v2)
00463     {v1.x -= v2.x; v1.y -= v2.y; v1.z -= v2.z; }
00464 /// add a deVec3d to another one (overloaded operator+=)
00465 static inline void operator+=(deVec3d &v1, const deVec3d &v2)
00466     {v1.x += v2.x; v1.y += v2.y; v1.z += v2.z; }
00467 /// multiply a deVec3d by a scalar value (overloaded operator*=)
00468 static inline void operator*=(deVec3d &v1, deDouble d)
00469     {v1.x *= d; v1.y *= d; v1.z *= d; }
00470 /// divide a deVec3d by a scalar value (overloaded operator/=)
00471 static inline void operator/=(deVec3d &v1, deDouble d)
00472     {deDouble d2 = 1/d; v1.x *= d2; v1.y *= d2; v1.z *= d2; }
00473 #ifdef _DEBUG
00474 // this should work even on packing of 8 due to a double's size
00475 static inline deDouble & Vec3d_GetElement(const deVec3d& v, long i)
00476     {if (i < 0 || i >= 3) DEBUGRETURN(*((deDouble*)&v),"Vec3d_GetElement: Invalid index"); return *( ((deDouble*)&v) + i ); }
00477 #else
00478 /// obtain a reference to an indexed value inside a 3d vector (valid index values: {0,1,2}, map to {x,y,z})
00479 static inline deDouble & Vec3d_GetElement(const deVec3d& v, long i)
00480     {return *(((deDouble*)&v) + i); }
00481 #endif
00482 
00483 /// compute the inverse of a deVertex (overloaded operator-)
00484 static inline deVertex operator-(const deVertex &v)
00485     {deVertex ret={-v.x,-v.y,-v.z};return ret;}
00486 /// compute the component difference between two deVertex (overloaded operator-)
00487 static inline deVertex operator-(const deVertex &v1, const deVertex &v2)
00488     {deVertex ret={v1.x-v2.x,v1.y-v2.y,v1.z-v2.z};return ret;}
00489 /// compute the component sum of two deVertex (overloaded operator+)
00490 static inline deVertex operator+(const deVertex &v1, const deVertex &v2)
00491     {deVertex ret={v1.x+v2.x,v1.y+v2.y,v1.z+v2.z};return ret;}
00492 /// compute the scalar product of a deVertex and a floating-point value (overloaded operator*)
00493 static inline deVertex operator*(const deVertex &v1, deFloat f)
00494     {deVertex ret={v1.x*f,v1.y*f,v1.z*f};return ret;}
00495 /// subtract a deVertex from another one (overloaded operator-=)
00496 static inline void operator-=(deVertex &v1, const deVertex &v2)
00497     {v1.x -= v2.x; v1.y -= v2.y; v1.z -= v2.z; }
00498 /// add a deVertex to another one (overloaded operator+=)
00499 static inline void operator+=(deVertex &v1, const deVertex &v2)
00500     {v1.x += v2.x; v1.y += v2.y; v1.z += v2.z; }
00501 /// multiply a deVertex by a scalar value (overloaded operator*=)
00502 static inline void operator*=(deVertex &v1, deFloat d)
00503     {v1.x *= d; v1.y *= d; v1.z *= d; }
00504 /// divide a deVertex by a scalar value (overloaded operator/=)
00505 static inline void operator/=(deVertex &v1, deFloat d)
00506     {deFloat d2 = 1/d; v1.x *= d2; v1.y *= d2; v1.z *= d2; }
00507 
00508 static inline deTexCoord operator-(const deTexCoord &v1, const deTexCoord &v2)
00509     {deTexCoord ret={v1.u-v2.u,v1.v-v2.v};return ret;}
00510 static inline deTexCoord operator+(const deTexCoord &v1, const deTexCoord &v2)
00511     {deTexCoord ret={v1.u+v2.u,v1.v+v2.v};return ret;}
00512 static inline deTexCoord operator*(const deTexCoord &v1, deFloat f)
00513     {deTexCoord ret={v1.u*f,v1.v*f};return ret;}
00514 static inline void operator-=(deTexCoord &v1, const deTexCoord &v2)
00515     {v1.u -= v2.u; v1.v -= v2.v; }
00516 static inline void operator+=(deTexCoord &v1, const deTexCoord &v2)
00517     {v1.u += v2.u; v1.v += v2.v; }
00518 static inline void operator*=(deTexCoord &v1, deFloat d)
00519     {v1.u *= d; v1.v *= d; }
00520 static inline void operator/=(deTexCoord &v1, deFloat d)
00521     {deFloat d2 = 1/d; v1.u *= d2; v1.v *= d2; }
00522 
00523 /// multiply each component of a deColor by the corresponding component of another
00524 static inline void operator*=(deColor& lhs, const deColor& rhs)
00525     {lhs.a *= rhs.a; lhs.r *= rhs.r; lhs.g *= rhs.g; lhs.b *= rhs.b;}
00526 
00527 /// "squeeze" the components of a deVec3d: if they are within Epsilon units of zero, set them to zero.
00528 /// Useful for getting "perfect" orthographic orientations after moving around a bit
00529 void Vec3d_Squeeze(deVec3d &v, deDouble Epsilon = 0.00001);
00530 /// compute the cross product of two deVec3d
00531 void Vec3d_Cross(const deVec3d &V1, const deVec3d &V2, deVec3d &Result);
00532 /// compute the cross product of two deVertex
00533 void Vec3d_Cross(const deVertex &V1, const deVertex &V2, deVertex &Result);
00534 static inline deVec3d Vec3d_Cross(const deVec3d &V1, const deVec3d &V2)
00535     {deVec3d ret; Vec3d_Cross(V1,V2,ret); return ret;}
00536 /// normalize a deVec3d
00537 /// @return the length of the original vector
00538 deDouble Vec3d_Normalize(deVec3d &V);
00539 /// normalize a deVertex
00540 /// @return the length of the original vector
00541 deFloat Vertex_Normalize(deVertex &V);
00542 /// compute the 32-bit deARGB value for a normalized deVec3d (for dot3 bumpmapping)
00543 deARGB Vec3d_ConvertToDot3(const deVec3d &V1, deFloat Height);
00544 deARGB Vec3d_ConvertToDot3Clamp(const deVec3d &V1, deFloat Height);
00545 
00546 /// Some useful geometry methods
00547 namespace deGeometry
00548 {
00549     // standard true/false test functions
00550     /// tests whether the inner AABB is actually inside the outer AABB
00551     deBoolean BoxInBox(const deVec3d & OuterMin, const deVec3d & OuterMax, const deVec3d & InnerMin, const deVec3d & InnerMax);
00552     /// tests whether the inner box is actually inside the outer box
00553     deBoolean BoxInBox(const deAABB & OuterBox, const deAABB & InnerBox);
00554     /// tests whether two AABBs intersect
00555     deBoolean BoxBoxIntersect(const deVec3d & Min1, const deVec3d & Max1, const deVec3d & Min2, const deVec3d & Max2);
00556     /// tests whether two AABBs intersect
00557     deBoolean BoxBoxIntersect(const deAABB & Box1, const deAABB & Box2);
00558     /// tests whether a point lies within an AABB
00559     deBoolean PointInBox(const deVec3d & pt, const deVec3d &Min, const deVec3d &Max);
00560     /// tests whether a point lies within an AABB
00561     deBoolean PointInBox(const deVec3d & pt, const deAABB & Box);
00562     /// returns the distance from a plane to a point, along the plane normal
00563     static inline deDouble PlaneDist(const deVec3d & pt, const deVec3d & norm, const deDouble & dist)
00564     {
00565         return Vec3d_Dot(pt, norm) - dist;
00566     }
00567     /// tests whether a point lies on the front of a plane (positive half-space)
00568     static inline deBoolean PointOnPlaneFront(const deVec3d & pt, const deVec3d & norm, const deDouble & dist)
00569     { return (Vec3d_Dot(pt,norm) >= dist) ? deTRUE : deFALSE; } 
00570     /// tests whether a point lies on the back of a plane (negative half-space)
00571     static inline deBoolean PointOnPlaneBack(const deVec3d & pt, const deVec3d & norm, const deDouble & dist)
00572     { return (Vec3d_Dot(pt,norm) <= dist) ? deTRUE : deFALSE; } 
00573     /// tests whether a point lies within an AABB
00574     static inline deBoolean PointInAABB(const deVec3d &Point, const deVec3d &Min, const deVec3d &Max)
00575     {
00576         if (Point.x < Min.x || Point.y < Min.y || Point.z < Min.z) return deFALSE;
00577         if (Point.x > Max.x || Point.y > Max.y || Point.z > Max.z) return deFALSE;
00578         return deTRUE;
00579     }
00580     /// calculates the geometric center of an AABB
00581     static inline void AABBCenter(const deAABB & bbox, deVec3d & vec)
00582     {
00583         vec = bbox.Min; vec += bbox.Max; vec *= 0.5;
00584     }
00585     /*
00586     needs fixing, radius is conservative
00587     /// calculates circumscribed radius of an AABB, from the origin
00588     static inline deDouble AABBRadius(const deAABB & BBox)
00589     {
00590         deDouble len1, len2;
00591         len1 = Vec3d_LengthSq(BBox.Min);
00592         len2 = Vec3d_LengthSq(BBox.Max);
00593         if (len1 < 1 && len2 < 1)
00594             len1 = sqrt(min(len1, len2));
00595         else
00596             len1 = sqrt(max(len1, len2));
00597         return len1;
00598     }
00599     */
00600     /// calculates diagonal size of an AABB, from min to max points
00601     static inline deDouble AABBDiagonal(const deAABB & BBox)
00602     {
00603         deVec3d len;
00604         len = BBox.Max;
00605         len -= BBox.Min;
00606         return Vec3d_Length(len);
00607     }
00608     /// tests whether a point lies within an AABB
00609     static inline deBoolean PointInAABB(const deVec3d &Point, const deAABB & Box)
00610     { return PointInAABB(Point, Box.Min, Box.Max); }
00611     /// expand a given AABB by adding a point. Result: BBox is enlarged to hold input BBox space and pt
00612     static inline void AABBAddPoint(deAABB & BBox, const deVec3d & pt)
00613     {
00614         BBox.Min.x = min(BBox.Min.x, pt.x);
00615         BBox.Min.y = min(BBox.Min.y, pt.y);
00616         BBox.Min.z = min(BBox.Min.z, pt.z);
00617         BBox.Max.x = max(BBox.Max.x, pt.x);
00618         BBox.Max.y = max(BBox.Max.y, pt.y);
00619         BBox.Max.z = max(BBox.Max.z, pt.z);
00620     }
00621     /// compute the union of two AABBs, and store the resulting AABB in the first argument (In_Out)
00622     static inline void AABBUnion(deAABB & In_Out, const deAABB & Input)
00623     {
00624         In_Out.Min.x = min(In_Out.Min.x, Input.Min.x);
00625         In_Out.Min.y = min(In_Out.Min.y, Input.Min.y);
00626         In_Out.Min.z = min(In_Out.Min.z, Input.Min.z);
00627         In_Out.Max.x = max(In_Out.Max.x, Input.Max.x);
00628         In_Out.Max.y = max(In_Out.Max.y, Input.Max.y);
00629         In_Out.Max.z = max(In_Out.Max.z, Input.Max.z);
00630     }
00631     /// test whether two AABBs intersect, using a half-open interval
00632     static inline deBoolean AABBIntersect(const deVec3d &Min1, const deVec3d &Max1, const deVec3d &Min2, const deVec3d &Max2)
00633     {
00634         // if one box's max is less than the other's min, they don't intersect
00635         if (Max1.x < Min2.x || Max1.y < Min2.y || Max1.z < Min2.z) return deFALSE;
00636         // and vice-versa
00637         if (Max2.x < Min1.x || Max2.y < Min1.y || Max2.z < Min1.z) return deFALSE;
00638         // otherwise, they do (I think)
00639         return deTRUE;
00640     }
00641     /// test whether two AABBs intersect, using a half-open interval
00642     static inline deBoolean AABBIntersect(const deAABB & Box1, const deAABB & Box2)
00643     { return AABBIntersect(Box1.Min, Box1.Max, Box2.Min, Box2.Max); }
00644     /// tests whether the inner AABB is actually inside the outer AABB
00645     static inline deBoolean AABBInAABB(const deVec3d &InMin, const deVec3d &InMax, const deVec3d &OutMin, const deVec3d &OutMax)
00646     {
00647         // if the inner box's min is less than the outer box's min, it's not inside
00648         if (InMin.x < OutMin.x || InMin.y < OutMin.y || InMin.z < OutMin.z) return deFALSE;
00649         // and opposite relation with max
00650         if (InMax.x > OutMax.x || InMax.y > OutMax.y || InMax.z > OutMax.z) return deFALSE;
00651         // otherwise, they do (I think)
00652         return deTRUE;
00653     }
00654     /// tests whether the inner AABB is actually inside the outer AABB
00655     static inline deBoolean AABBInAABB(const deAABB & InBox, const deAABB & OutBox)
00656     { return AABBInAABB(InBox.Min, InBox.Max, OutBox.Min, OutBox.Max); }
00657     /// classify where an AABB lies relative to a plane.
00658     /// -1 => all negative, 0 => intersects, 1 => all positive
00659     int AABBPlaneClassify(const deAABB & BBox, const deVec3d & Norm, const deDouble & Dist);
00660     
00661     // these take a non-const reference to fill in values
00662     /// intersect a plane and a line segment
00663     deBoolean PlaneLineIntersect(const deVec3d & Norm, const deDouble & Dist, const deVec3d & Pt1, const deVec3d & Pt2, deVec3d & Res, deDouble & Percent);
00664     /// intersect a plane and a ray
00665     deBoolean PlaneRayIntersect(const deVec3d & Norm, const deDouble & Dist, const deVec3d & Start, const deVec3d & Dir, deDouble & Multiple);
00666     /// intersect a sphere and a ray
00667     deBoolean SphereRayIntersect(const deVec3d & Center, const deDouble & Radius, const deVec3d & Start, const deVec3d & Dir, deDouble & Multiple);
00668     /// intersect a sphere and a line segment
00669     deBoolean SphereLineIntersect(const deVec3d & Center, const deDouble & Radius, const deVec3d & Start, const deVec3d & End, deVec3d & Res, deDouble & Percent);
00670     /// perform a linear-sweep AABB collision test
00671     deBoolean AABBCollision(const deAABB & MovingBox, const deVec3d & MoveStart, const deVec3d & MoveEnd, 
00672         const deAABB & StaticBox, const deVec3d & StaticPos, deVec3d & MovingColPt, deVec3d & ColNormal, deDouble & Percent);
00673     /// create an AABB that contains a set of points
00674     deBoolean ConstructAABB(const deVec3d * VecArray, long NumVecs, deVec3d & Min, deVec3d & Max);
00675     /// create an OBB using an AABB and a transformation
00676     deBoolean MakeOBBFromAABB(const deAABB & LocalBox, const deTransform & WorldMatrix, deOBB & WorldBox);
00677     /// get the 8 corners of an AABB
00678     deBoolean GetPointsOfAABB(const deAABB & BBox, deVec3d * ArrayOf8);
00679     /// get the 8 corners of an OBB
00680     deBoolean GetPointsOfOBB(const deOBB & WorldBox, deVec3d * ArrayOf8);
00681     /// create an AABB that contains a set of points
00682     static inline deBoolean ConstructAABB(const deVec3d * VecArray, long NumVecs, deAABB & Box)
00683     { return ConstructAABB(VecArray, NumVecs, Box.Min, Box.Max); }
00684     /// create an AABB that contains an OBB
00685     static inline deBoolean MakeAABBFromOBB(const deOBB & InBox, deAABB & OutBox)
00686     {
00687         deVec3d vecarray[8];
00688         if (!GetPointsOfOBB(InBox, vecarray)) return deFALSE;
00689         if (!ConstructAABB(vecarray, 8, OutBox)) return deFALSE;
00690         return deTRUE;
00691     }
00692     /// create a BSphere from an AABB
00693     static inline void MakeBoundSphereFromAABB(const deAABB & BBox, deBoundSphere & OutSphere)
00694     {
00695         OutSphere.Radius = AABBDiagonal(BBox) * 0.5;
00696         AABBCenter(BBox, OutSphere.Center);
00697     }
00698     /// intersect an OBB and a ray
00699     deBoolean RayOBBIntersect(const deVec3d & RayStart, const deVec3d & RayDir, const deOBB & Box, deVec3d & Result, deVec3d & Normal, deDouble & Percent);
00700     
00701     /// intersect a plane and a line segment
00702     static inline deBoolean PlaneLineIntersect(const dePlane & Plane, const deVec3d & Pt1, const deVec3d & Pt2, deVec3d & Res, deDouble & Percent)
00703     { return PlaneLineIntersect(Plane.Norm, Plane.Dist, Pt1, Pt2, Res, Percent); }
00704     /// intersect a plane and a ray
00705     static inline deBoolean PlaneRayIntersect(const dePlane & Plane, const deVec3d & Start, const deVec3d & Dir, deDouble & Multiple)
00706     { return PlaneRayIntersect(Plane.Norm, Plane.Dist, Start, Dir, Multiple); }
00707 
00708     /// interpolate a Vec3d over a range [0,1]
00709     static inline void Vec3d_Interpolate(deVec3d & Output, const deVec3d & In1, const deVec3d& In2, deDouble Percent)
00710     {
00711         Output.x = In1.x*(1-Percent) + In2.x*Percent;
00712         Output.y = In1.y*(1-Percent) + In2.y*Percent;
00713         Output.z = In1.z*(1-Percent) + In2.z*Percent;
00714     }
00715     /// interpolate a Vertex over a range [0,1]
00716     static inline void Vertex_Interpolate(deVertex & Output, const deVertex & In1, const deVertex& In2, deDouble Percent)
00717     {
00718         Output.x = deFloat(In1.x*(1-Percent) + In2.x*Percent);
00719         Output.y = deFloat(In1.y*(1-Percent) + In2.y*Percent);
00720         Output.z = deFloat(In1.z*(1-Percent) + In2.z*Percent);
00721     }
00722     /// interpolate a TexCoord2 over a range [0,1]
00723     static inline void TexCoord_Interpolate(deTexCoord2 & Output, const deTexCoord2 & In1, const deTexCoord2& In2, deDouble Percent)
00724     {
00725         Output.u = deFloat(In1.u*(1-Percent) + In2.u*Percent);
00726         Output.v = deFloat(In1.v*(1-Percent) + In2.v*Percent);
00727     }
00728     /// interpolate an ARGB over a range [0,1]
00729     static inline void ARGB_Interpolate(deARGB& Output, deARGB Color1, deARGB Color2, deFloat Percent)
00730     {
00731         Output = 
00732             (deARGB((1-Percent)*((Color1>>24)&0xff) + (Percent)*((Color2>>24)&0xff)) << 24) |
00733             (deARGB((1-Percent)*((Color1>>16)&0xff) + (Percent)*((Color2>>16)&0xff)) << 16) |
00734             (deARGB((1-Percent)*((Color1>> 8)&0xff) + (Percent)*((Color2>> 8)&0xff)) << 8)  |
00735             (deARGB((1-Percent)*((Color1    )&0xff) + (Percent)*((Color2    )&0xff)));
00736     }
00737 };
00738 
00739 
00740 #endif

Generated on Mon Sep 12 19:58:31 2005 for Destiny3D by doxygen1.3-rc3